/*
 * Copyright (c) 2010 Mathias Garbe <code@mathias-garbe.de>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "GameWindow.hpp"

GameWindow::GameWindow(QWidget *parent, Qt::WFlags flags)
: QDialog(parent, flags)
{
    QWidget::setWindowModality(Qt::WindowModal);

    ui.setupUi(this);

    this->closed = false;
	this->gameMutex = new QMutex();
}

GameWindow::~GameWindow()
{
	delete this->gameMutex;
}

void _cncnet_launch(void *f)
{    
    ThreadArgs args = *(ThreadArgs*)f;
	args.gameMutex->lock();
    LauncherHooks::incomingPacketInstance(args.incomingPackets);
    args.returnCode = cncnet_launch(args.gameExe.c_str(), args.gameArgs.c_str());
    LauncherHooks::incomingPacketInstance(0, true);
	args.gameMutex->unlock();
}

void GameWindow::show(GameInfo *game, MainWindow *mainWin,  ThreadingVector<Packet> *incomingPackets)
{
	// Move window to middle of the screen
    QRect screen = QApplication::desktop()->screenGeometry();
    this->move(screen.width()/2 - this->width()/2, screen.height()/2 - this->height()/2);
    QWidget::show();

    this->closed = false;

    // Set thread arguments
    args.incomingPackets = incomingPackets;
    args.gameExe = game->getExe();
    args.gameArgs = game->getArgs();
    args.returnCode = -1;
    args.gameMutex = this->gameMutex;

    QSettings settings;

    // set game handle to game ini
    std::string nickname = settings.value("General/GameHandle", "").toString().toStdString();
    int gameID = game->getType();
    std::string gameIni = game->getPath().append(Games::getGameIniName(gameID));
    if(gameID < 3)
    {
        WritePrivateProfileStringA("MultiPlayer", "Handle", nickname.c_str(), gameIni.c_str());
    }
    else
    {
        // RA2 and YR are using bytes separated by comma...
        // I hate them.
        std::stringstream byteNick;
        for(unsigned int i = 0; i < nickname.size(); i++)
        {
            int c = nickname[i];
            byteNick << std::hex << c << ",";
        }
        WritePrivateProfileStringA("MultiPlayer", "Handle", byteNick.str().c_str(), gameIni.c_str());
    }

    if(settings.value("CNC-DDraw/Enabled", false).toBool() && gameID < 2)
    {
        std::string ddrawIni = game->getPath().append("ddraw.ini");
        WritePrivateProfileStringA("ddraw", "width", settings.value("CNC-DDraw/Width", "0").toString().toStdString().c_str(), ddrawIni.c_str());
        WritePrivateProfileStringA("ddraw", "height", settings.value("CNC-DDraw/Height", "0").toString().toStdString().c_str(), ddrawIni.c_str());

        std::string windowed = "false";
        if(settings.value("CNC-DDraw/Windowed", true).toBool())
        {
            windowed = "true";
        }
        WritePrivateProfileStringA("ddraw", "windowed", windowed.c_str(), ddrawIni.c_str());

        std::string mouse = "false";
        if(settings.value("CNC-DDraw/AdjustMouse", false).toBool())
        {
            mouse = "true";
        }
        WritePrivateProfileStringA("ddraw", "adjmouse", mouse.c_str(), ddrawIni.c_str());

        WritePrivateProfileStringA("ddraw", "bpp", settings.value("CNC-DDraw/Color", "0").toString().toStdString().c_str(), ddrawIni.c_str());
        WritePrivateProfileStringA("ddraw", "maxfps", settings.value("CNC-DDraw/Fps", "0").toString().toStdString().c_str(), ddrawIni.c_str());
        WritePrivateProfileStringA("ddraw", "filter", settings.value("CNC-DDraw/Filter", "0").toString().toStdString().c_str(), ddrawIni.c_str());
    }

    // set custom config stuff
    memset(config_server, 0, 64);
    if(settings.value("Network/Server", "lobby.cncnet.cnc-comm.com").toString().toStdString().size() >= 65)
    {
        throw std::runtime_error("GameWindow::show(...) Network/Server too long, buffer overflowing.");
    }
    strcpy_s(config_server, 64, settings.value("Network/Server", "lobby.cncnet.cnc-comm.com").toString().toStdString().c_str());
    //strcpy(config_server, settings.value("Network/Server", "lobby.cncnet.cnc-comm.com").toString().toStdString().c_str());
    config_server_port = settings.value("Network/ServerPort", "8054").toInt();
    config_port = settings.value("Network/ClientPort", "8054").toInt();

    config_port_force = settings.value("Network/ClientPortForce", false).toBool();

    mainWin->updateOnlineStatus();
    _beginthread(_cncnet_launch, 0, (void*)&args);
    this->hide();
}

void GameWindow::closeEvent(QCloseEvent *event)
{
    if(this->isIngame())
    {
        event->ignore();
    }

    this->closed = true;
}
